//! 对应struct的相关方法实现

use quote::quote;

/// 结构的实例方法实现
pub(crate) mod instance_method_impl;
/// 实现Self::orm_delete相关方法
mod orm_delete_impl;
/// 实现Self::orm_exist相关方法
mod orm_exist_impl;
/// 实现Self::orm_query相关方法
mod orm_query_impl;
/// 实现结构体join SQL
mod orm_struct_join_impl;
/// 实现Self::orm_update相关方法
mod orm_update_impl;

/// 实现struct的相关方法
pub(super) fn impl_struct_fn(
    ast: &syn::DeriveInput,
    table_name: &str,
) -> instance_method_impl::TinyOrmStructInfo {
    let struct_name = &ast.ident;

    let mut orm_struct_info = instance_method_impl::impl_instance_method(ast, table_name);
    // 主键方法实现
    let instance_method_impl::TinyOrmStructInfo {
        token: orm_instance_token,
        ..
    } = orm_struct_info;

    // 查询、删除和更新方法实现
    let orm_query_token = orm_query_impl::impl_struct_orm_query(ast).unwrap_or_else(|| quote! {});
    let orm_delete_token =
        orm_delete_impl::impl_struct_orm_delete(ast).unwrap_or_else(|| quote! {});
    let orm_update_token =
        orm_update_impl::impl_struct_orm_update(ast).unwrap_or_else(|| quote! {});
    let orm_exist_token = orm_exist_impl::impl_struct_orm_exist(ast).unwrap_or_else(|| quote! {});
    // 解析未与特定字段关联的结构体join信息
    let orm_struct_join_infos = orm_struct_join_impl::parse_struct_orm_join(ast);

    // 将结构体join相关信息附加到字段join中
    if !orm_struct_join_infos.is_empty() {
        orm_struct_info.select_field = format!(
            "{} {} {}",
            orm_struct_info.select_field,
            if orm_struct_info.select_field.is_empty() {
                ""
            } else {
                ","
            },
            orm_struct_join_infos
                .iter()
                .map(|info| info.select_field.as_str())
                .collect::<Vec<_>>()
                .join(",")
        );
        if let Some(select_join_sql) = orm_struct_info.select_join_sql {
            orm_struct_info.select_join_sql = Some(format!(
                "{} {} {}",
                select_join_sql,
                if select_join_sql.is_empty() { "" } else { "," },
                orm_struct_join_infos
                    .iter()
                    .map(|info| info.join.as_str())
                    .collect::<Vec<_>>()
                    .join(",")
            ));
        } else {
            orm_struct_info.select_join_sql = Some(
                orm_struct_join_infos
                    .iter()
                    .map(|info| info.join.as_str())
                    .collect::<Vec<_>>()
                    .join(",")
                    .into(),
            );
        }
    }
    orm_struct_info.token = quote! {
        impl #struct_name{
            #orm_query_token
            #orm_delete_token
            #orm_instance_token
            #orm_update_token
            #orm_exist_token
        }
    };

    orm_struct_info
}
